import { FC, useEffect, useRef, useState } from 'react'
import './style.less'
import { getCompanyInfoDetailQueryBusinessInformation, postCompanyInfoDetailSupply } from '@/api/companyDetail/MarketConditions'
import G6 from '@antv/g6'
import _ from 'lodash'
import { HsAdminSpin } from '@hs-admin/base-components'
import { openCompanyDetail } from 'hs-react-company'

interface Props {
  companyCode: string
}
const SupplyDemand: FC<Props> = (props: Props) => {
  const { companyCode } = props
  const [isShow, setIsShow] = useState(false)
  const data = useRef<any>({
    name: '',
    hasChild: 1,
    collapsed: false,
    children: [],
    /** 有子级的加 */
    anchorPoints: [
      [1, 0.5],
      [0, 0.5]
    ]
  })
  /** 图表基础字号 */
  const fontSize = 16
  const [loading, setloading] = useState(true)
  const hasInit = useRef(false)

  /**
   * @description 文本超出隐藏 (字段, 最大长度, 字体大小)
   * @param str 文本
   * @param maxWidth 长度
   * @returns string 返回文本
   */
  const fittingString = (str: string, maxWidth: number) => {
    const ellipsis = '...'
    const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0]
    let currentWidth = 0
    let res = str
    const pattern = new RegExp('[\u4E00-\u9FA5]+')
    str.split('').forEach((letter: any, index: number) => {
      if (currentWidth > maxWidth - ellipsisLength) return
      if (pattern.test(letter)) {
        currentWidth += fontSize
      } else {
        currentWidth += G6.Util.getLetterWidth(letter, fontSize)
      }
      if (currentWidth > maxWidth - ellipsisLength) {
        /** 若需要省略号，tooltip模式，可在此设置 */
        res = `${str.substring(0, index)}${ellipsis}`
      }
    })
    return res
  }

  /**
   * @description 获取文本的长度
   * @param str 文本
   * @param maxWidth 设置的最大长度
   * @returns number 最大长度
   */
  const getTextSize = (str: string, maxWidth: number) => {
    const width = G6.Util.getTextSize(str, fontSize)[0]
    /** 若需要省略号，tooltip模式，可在此设置 */
    return width > maxWidth ? maxWidth : width
  }
  /** 初始化图表 */
  function init() {
    /** 自定义节点 */
    G6.registerNode('tree-node', {
      draw(cfg: any, group: any) {
        let rect: any

        let name = cfg.name

        /** 左侧 */
        if (cfg.position === 'left') {
          /** 左侧企业添加供应商 */
          if (cfg.depth === 2) {
            name = `【供应商】${cfg.name}`
          }
          /** 左侧盒子 */
          rect = group.addShape('rect', {
            attrs: {
              x: 190 - getTextSize(name, 190), // x 轴移动距离
              y: 0, // y 轴移动距离
              width: getTextSize(name, 190) + 54, // 宽
              height: 40, // 高
              fill: '#fff',
              stroke: '#E6E6E6',
              fontSize: 16,
              fontWeight: 600,
              radius: 4,
              cursor: 'pointer'
            },
            name: 'big-rect-shape'
          })
          /** 左侧文本 */
          group.addShape('text', {
            attrs: {
              text: fittingString(name, 190),
              x: 190 - getTextSize(name, 190) + 27,
              y: 20,
              fontSize: 16,
              textAlign: 'left',
              textBaseline: 'middle',
              fill: '#333333',
              cursor: 'pointer'
            },
            name: 'text-shape'
          })
        }

        /** 右侧 */
        if (cfg.position === 'right') {
          /** 左侧企业添加客户 */
          if (cfg.depth === 2) {
            name = `【客户】${cfg.name}`
          }
          /** 右侧盒子 */
          rect = group.addShape('rect', {
            attrs: {
              x: 0, // x 轴移动距离
              y: 0, // y 轴移动距离
              width: getTextSize(name, 190) + 54, // 宽
              height: 40, // 高
              fill: '#fff',
              stroke: '#E6E6E6',
              fontSize: 16,
              fontWeight: 600,
              radius: 4,
              cursor: 'pointer'
            },
            name: 'big-rect-shape'
          })

          /** 右侧文本 */
          group.addShape('text', {
            attrs: {
              text: fittingString(name, 190),
              x: 27,
              y: 20,
              fontSize: 16,
              textAlign: 'left',
              textBaseline: 'middle',
              fill: '#333333',
              cursor: 'pointer'
            },
            name: 'text-shape'
          })
        }

        /** 根节点 */
        if (cfg.depth === 0) {
          /** 盒子 */
          rect = group.addShape('rect', {
            attrs: {
              x: 0, // x 轴移动距离
              y: 0, // y 轴移动距离
              width: getTextSize(name, 190) + 54, // 宽
              height: 40, // 高
              fill: '#0779FF',
              stroke: '#E6E6E6', // 边框色
              fontSize: 16,
              fontWeight: 600,
              radius: 4,
              cursor: 'pointer'
            },
            name: 'big-rect-shape'
          })

          /** 文本 */
          group.addShape('text', {
            attrs: {
              text: fittingString(name, 190),
              x: 27,
              y: 20,
              fontSize: 16,
              textAlign: 'left',
              textBaseline: 'middle',
              fill: '#fff',
              cursor: 'pointer'
            },
            name: 'text-shape'
          })
        }

        /** 根据是否有子节点，添加按钮 */
        /** 有子级且层级不为3的展示按钮 */
        const hasChildren = cfg?.children && cfg.depth !== 2
        if (hasChildren) {
          /** 左侧 */
          if (cfg.position === 'left') {
            group.addShape('marker', {
              attrs: {
                x: 190 - getTextSize(name, 190) + 15,
                y: 19,
                r: 6,
                symbol: cfg.collapsed ? G6.Marker.expand : G6.Marker.collapse,
                stroke: '#666',
                fill: '#fff',
                lineWidth: 1,
                cursor: 'pointer' // 鼠标变手
              },
              name: 'collapse-icon',
              modelId: cfg.id
            })
          } else {
            /** 右侧，同时也是根节点右侧按钮 */
            group.addShape('marker', {
              attrs: {
                x: getTextSize(name, 190) + 39,
                y: 19,
                r: 6,
                symbol: cfg.collapsed ? G6.Marker.expand : G6.Marker.collapse,
                stroke: '#666',
                fill: '#fff',
                lineWidth: 1,
                cursor: 'pointer' // 鼠标变手
              },
              name: 'collapse-icon',
              modelId: cfg.id
            })
          }
        }
        /** 根节点左侧按钮 */
        if (cfg.depth === 0) {
          group.addShape('marker', {
            attrs: {
              x: 15,
              y: 19,
              r: 6,
              symbol: cfg.collapsed ? G6.Marker.expand : G6.Marker.collapse,
              stroke: '#666',
              fill: '#fff',
              lineWidth: 1,
              cursor: 'pointer' // 鼠标变手
            },
            name: 'collapse-icon',
            modelId: cfg.id
          })
        }
        return rect
      }
    })

    /** 自定义边 */
    G6.registerEdge(
      'line-arrow',
      {
        getPath(points: any[]) {
          const startPoint = points[0]
          const endPoint = points[1]
          return [
            ['M', startPoint.x, startPoint.y],
            ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, startPoint.y],
            ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, endPoint.y],
            ['L', endPoint.x, endPoint.y]
          ]
        }
      },
      'line'
    )

    /** 添加tooltip */
    const tooltip = new G6.Tooltip({
      offsetX: 10,
      offsetY: 20,
      getContent(e: any) {
        const outDiv = document.createElement('div')
        outDiv.style.maxWidth = '500px'
        outDiv.innerHTML = `
        <span>
         ${e.item.getModel().name}
        </span>`
        return outDiv
      },
      itemTypes: ['node']
    })
    const container = document.getElementById('container') as HTMLElement

    const width = container?.scrollWidth || 500
    const height = container?.scrollHeight || 500

    const graph = new G6.TreeGraph({
      container,
      width,
      height,
      plugins: [tooltip],
      modes: {
        default: [
          'drag-canvas',
          'zoom-canvas',
          /** 高亮节点与边 */
          'activate-relations'
        ]
      },
      defaultNode: {
        type: 'tree-node'
      },
      defaultEdge: {
        /** 自定义边 */
        type: 'line-arrow',
        style: {
          stroke: '#E6E6E6'
        }
      },
      layout: {
        type: 'mindmap',
        direction: 'H',
        getId: function getId(d: any) {
          return d.id
        },
        getHeight: () => {
          return 32
        },
        getWidth: () => {
          return 120
        },
        getVGap: () => {
          return 20
        },
        getHGap: () => {
          return 160
        },
        /** 将节点动态分边 */
        getSide: (d: any) => {
          if (d.data.position === 'left') {
            return 'left'
          }
          return 'right'
        }
      }
    })

    /** 点击企业名称弹出又一个企业详情，无限套娃 */
    const handleCompanyNameClick = (evt: any) => {
      const model = evt.item.getModel()
      /** 根节点和产品名称不弹 */
      if ([0, 1].includes(model.depth)) return
      openCompanyDetail(model.companyCode)
    }
    /** 监听文本点击 */
    graph.on('text-shape:click', (e) => {
      handleCompanyNameClick(e)
    })

    /** 监听按钮点击 */
    graph.on('collapse-icon:click', async (evt) => {
      /** 被操作的节点 item */
      const item = evt.item
      /** 被操作的节点数据 */
      const model = item?.getModel() as any

      /** 已格式化的数据直接收起和展开 */
      if (model.children[0]?.anchorPoints) {
        const target = evt.target
        const id = target.get('modelId')
        const item2 = graph.findById(id)
        const nodeModel = item2.getModel() as any
        nodeModel.collapsed = !nodeModel.collapsed
        graph.layout()
        graph.setItemState(item2, 'collapse', nodeModel.collapsed)
        graph.updateItem(item2, {
          collapsed: nodeModel.collapsed
        })
      } else {
        /** 这里是为了点击加载需求设置的，然而本页面要求直接展开全部节点，故而这里可以不看 */
        /** 未格式化的数据，格式化数据 */
        setloading(true)
        const children = JSON.parse(JSON.stringify(model.children))
        children.forEach(
          (k: {
            children: { lenght: any }
            anchorPoints: number[][]
            code: number
            id: string
            category: any
            position: string
            collapsed: boolean
          }) => {
            /** anchorPoints用来设置折现拐点的，一定要设置！！！！！ */
            /** 有子级的 */
            if (k.children?.lenght) {
              k.anchorPoints = [
                [1, 0.5],
                [0, 0.5]
              ]
            } else if (model.category === 0) {
              /** 无子级的, 在左侧的 */
              k.anchorPoints = [[1, 0.5]]
            } else {
              /** 无子级的, 在右侧的 */
              k.anchorPoints = [[0, 0.5]]
            }
            /** id不能重复，拼上节点是左侧，还是右侧，用于判断连线箭头的方向 */
            let splitStr = k.code + Date.now()
            if (!k.code) {
              splitStr = Date.now()
            }
            k.id = (model.category === 0 ? 'left' : 'right') + splitStr
            /** category用于点击加载传递参数 */
            k.category = model.category

            /** position用于判断节点怎么画 */
            k.position = model.category === 0 ? 'left' : 'right'

            /** 新加载的数据初始状态都为折叠状态 */
            k.collapsed = true
          }
        )

        /** 展开当前节点 */
        model.collapsed = false
        /** 更新子节点 */
        graph.updateChildren(children, model.id)

        setloading(false)
      }

      /** 将中心动画地移动到当前操作节点，并配置动画 */
      graph.focusItem(evt.item as any, true, {
        easing: 'easeCubic',
        duration: 400
      })
    })

    /** 这里重复接入，是为了初始化数据，为了下方的条件判断 */
    // graph.data(_.cloneDeep(data.current))
    // graph.render()
    // graph.fitView()

    /** 该方法可以为不同边进行不同的配置 */
    graph.edge(function (e) {
      const id = e.id as string
      const isRight = id.indexOf('left') === -1

      /** 右侧给终止箭头 */
      if (isRight) {
        return {
          style: {
            endArrow: {
              // path: 'M 0,0 L 12,6 L 9,0 L 12,-6 Z',
              path: 'M 0,0 L 12,6 L 12,-6 Z',
              fill: '#E6E6E6'
            }
          }
        }
      }

      /** 左侧侧给终止箭头 */
      return {
        style: {
          startArrow: {
            // path: 'M 0,0 L 12,6 L 9,0 L 12,-6 Z',
            path: 'M 0,0 L 12,6 L 12,-6 Z',
            fill: '#E6E6E6'
          }
        }
      }
    })

    /** 控制初始展开层级 */
    G6.Util.traverseTree(data, (item: { depth: number; id: string; name: any; x: any; y: any; position: any }) => {
      if (item.depth > 0) {
        /** collapsed为true时默认收起 */
        // item.collapsed = true
      }
      item.id = `${item.name}${item.x}${item.y}${item.position || ''}` // id不能重复，拼上节点是左侧，还是右侧，用于判断连线箭头的方向
    })

    graph.data(_.cloneDeep(data.current))
    graph.render()
    graph.fitCenter()

    if (typeof window !== 'undefined')
      window.onresize = () => {
        if (!graph || graph.get('destroyed')) return
        if (!container || !container.scrollWidth || !container.scrollHeight) return
        graph.changeSize(container.scrollWidth, container.scrollHeight)
      }
    setloading(false)
  }

  const getData = async () => {
    // 获取当前企业名称
    getCompanyInfoDetailQueryBusinessInformation({ companyCode: companyCode || 'f70584e2d755ebcd7b58a11a281b0e70' }).then((res) => {
      data.current.name = res.data.companyName
    })

    const { data: res } = await postCompanyInfoDetailSupply({
      companyCode: companyCode || 'f70584e2d755ebcd7b58a11a281b0e70'
    })

    const { left, right } = res

    // 父公司放左侧
    left.forEach((k: { children: any[]; anchorPoints: number[][]; position: string; category: number }) => {
      /** anchorPoints用来设置折现拐点的，一定要设置！！！！！ */
      if (k.children?.length) {
        /** 有子级的 */
        k.anchorPoints = [
          [1, 0.5],
          [0, 0.5]
        ]
      } else {
        /** 无子级的 */
        k.anchorPoints = [[1, 0.5]]
      }
      /** position用于判断节点怎么画 */
      k.position = 'left'

      /** category用于点击加载传递参数 */
      k.category = 0

      /** 新加载的数据初始状态都为折叠状态 */
      // k.collapsed = true

      /** 因为目前只有2层，直接遍历 */
      if (k.children?.length) {
        k.children.forEach((e) => {
          /** 无子级的 */
          e.anchorPoints = [[0, 0.5]]
          /** category用于点击加载传递参数 */
          e.position = 'left'

          /** position用于判断节点怎么画 */
          e.category = 0

          /** 新加载的数据初始状态都为折叠状态 */
          // e.collapsed = true
        })
      }
    })
    // 子公司放右侧
    right.forEach((k: { children: any[]; anchorPoints: number[][]; position: string; category: number }) => {
      if (k.children?.length) {
        /** 有子级的 */
        k.anchorPoints = [
          [1, 0.5],
          [0, 0.5]
        ]
      } else {
        /** 无子级的 */
        k.anchorPoints = [[0, 0.5]]
      }
      /** category用于点击加载传递参数 */
      k.position = 'right'

      /** position用于判断节点怎么画 */
      k.category = 1

      /** 新加载的数据初始状态都为折叠状态 */
      // k.collapsed = true

      /** 因为目前只有2层，直接遍历 */
      if (k.children?.length) {
        k.children.forEach((e) => {
          /** 无子级的 */
          e.anchorPoints = [[0, 0.5]]
          /** category用于点击加载传递参数 */
          e.position = 'right'

          /** position用于判断节点怎么画 */
          e.category = 1

          /** 新加载的数据初始状态都为折叠状态 */
          // e.collapsed = true
        })
      }
    })
    data.current.children = [...left, ...right]
    /** 有值画图 */
    if (data.current.children.length) {
      setIsShow(true)
      setTimeout(() => {
        if (!hasInit.current) {
          hasInit.current = true
          init()
        }
      })
    } else {
      /** 无值隐藏该模块 */
      setIsShow(false)
      setloading(false)
    }
  }

  useEffect(() => {
    getData()
  }, [])

  return (
    <>
      {loading && <HsAdminSpin />}
      {isShow && (
        <div className="market-conditions-supply-demand-wrapper" id="供需关系图">
          <h3>供需关系</h3>
          <div className="chart_box">
            <div id="container"></div>
          </div>
        </div>
      )}
    </>
  )
}

export default SupplyDemand
